Elasticsearch QueryString 查詢語法筆記
最近開始想把 LOG 儲存在 Elasticsearch 裡,但這樣做需要有個方便查詢的 UI 介面,對我而言 Kibana 功能過於複雜,Postman 查詢又比較麻煩。後來發現了 Elasticvue 這個工具,選擇它的原因是它支援多種瀏覽器擴充套件及桌面應用程式版本。
Elasticvue 的查詢介面主要基於 query_string 語法,這是 Elasticsearch 中基於 Lucene 查詢語法的擴展版本。對熟悉 SQL 的使用者來說,query_string 比其他 DSL 語法更容易上手,因此我整理了一些常用的語法方便查閱。
可從 Elasticvue 官網 查看各個瀏覽器擴充套件,或是桌面應用程式的安裝檔案或連結。
測試版本:Elasticsearch 9.1.4
基本語法
基本 API 結構
{
"query": {
"query_string": {
"query": "your query string here", // 必要參數:查詢字串(使用 "*" 可搜尋所有文件)
"default_field": "content", // 選用參數:預設搜尋欄位,未指定,預設為 "*",搜尋全部欄位
"default_operator": "OR" // 選用參數:預設運算子,預設值為 OR
// 其他可選參數
}
},
"size": 10, // 選用參數:回傳結果數量,預設為 10
"from": 0, // 選用參數:起始位置,預設為 0
"sort": [] // 選用參數:結果排序
}未指定欄位時,QueryString 會在所有可搜尋欄位中進行搜尋。
查詢語法
1. 基本搜尋
簡單關鍵字搜尋:
apple多個詞彙(預設使用 OR 連接):
apple banana不同欄位類型的搜尋行為
Elasticsearch 對不同欄位型別使用不同分析策略(官方文件):
- text 欄位:使用 standard 分析器,會分詞並轉小寫。
- keyword 欄位:使用 keyword 分析器,保持完整字串不變。
- 數值/日期/布林欄位:不使用分析器,索引原始值。
- query_string:會依目標欄位型別選擇對應策略處理查詢字串。
| 欄位類型 | 查詢字串 | 行為說明 |
|---|---|---|
| text | apple banana | 等同 apple OR banana,找到任一詞彙即符合 |
| keyword | "apple" "banana" | 必須用雙引號明確搜尋多個完整字串,或著使用 apple OR banana |
| keyword | apple banana | 查不到,因為會被視為完整字串比對 |
| 數值/日期/布林 | "123" "456" | 多值搜尋必須用雙引號明確指定值,或著使用 123 OR 456 |
| 數值/日期/布林 | 123 456 | 查不到,因為 query_string 不會自動拆分多個完整值 |
JSON 多詞彙查詢範例(使用雙引號跳脫):
{
"query": {
"query_string": {
"query": "\"apple\" \"banana\""
}
}
}精確片語搜尋(使用雙引號):
"red apple"2. 布林運算子
AND 運算子(兩個詞都必須存在):
apple AND bananaOR 運算子(至少有一個詞必須存在):
apple OR bananaNOT 運算子(排除包含某詞的文件):
apple NOT banana加號(必須包含此詞):
+apple banana減號(必須排除此詞):
apple -bananaWARNING
英文運算子必需全部大寫。
3. 欄位指定查詢
針對特定欄位搜尋:
title:apple針對多個欄位的查詢:
title:apple AND content:banana多值查詢(OR 條件):
user_id:(1234 OR 5678)欄位存在性查詢:
_exists_:email // 查詢 email 欄位存在的文件,可以理解成不為 null
NOT _exists_:phone // 查詢 phone 欄位不存在的文件,可以理解成為 null欄位指定優先順序:查詢字串中明確指定欄位 > fields 參數 > default_field 參數。
4. 範圍查詢與比較運算子
範圍查詢:
price:[10 TO 20] // 閉區間,包含 10 和 20
price:{10 TO 20} // 開區間,不包含 10 和 20
price:[10 TO *] // 大於等於 10
price:[* TO 20] // 小於等於 20比較運算子:
price:>10 // 大於 10
price:>=10 // 大於等於 10
price:<20 // 小於 20
price:<=20 // 小於等於 20這兩種寫法在功能上大致相同,可依情境選擇使用。不過實測發現,範圍查詢語法在各種參數組合下的相容性較佳,以下為測試範例:
比較運算子使用限制:
比較運算子(>、>=、<、<=)在搭配 fields 陣列參數時會產生錯誤,但使用 default_field 或直接在查詢字串中指定欄位時可正常運作。
✅ 可正常使用的寫法:
// 方式 1:未指定欄位
{
"query": {
"query_string": {
"query": ">=10"
}
}
}
// 方式 2:在查詢字串中指定欄位
{
"query": {
"query_string": {
"query": "price:>=10"
}
}
}
// 方式 3:使用 default_field 參數
{
"query": {
"query_string": {
"query": ">=10",
"default_field": "price"
}
}
}❌ 會產生錯誤的寫法:
// 使用 fields 陣列會導致查詢失敗
{
"query": {
"query_string": {
"query": ">=10",
"fields": ["price"]
}
}
}✅ 解決方案:改用範圍查詢語法
範圍查詢語法([x TO y])與 fields 參數相容,可正常使用:
{
"query": {
"query_string": {
"query": "[10 TO *]",
"fields": ["price"]
}
}
}5. 萬用字元搜尋
萬用字元搜尋:
te?t // 問號代表一個字元
test* // 星號代表零個或多個字元6. 日期時間查詢
基本日期範圍查詢
使用範圍語法進行日期查詢:
timestamp:[2023-01-01 TO 2023-01-31]也可以使用相對時間進行查詢:
timestamp:>now-1d // 查詢過去 24 小時的資料常用相對時間表達式:
now-1h:一小時前now-1d:一天前now-1w:一週前now/d:今天開始(00:00:00)now/w:本週開始now/M:本月開始
日期時間格式
Elasticsearch 的 date 型別預設支援到毫秒精度,若需要奈秒精度可改用 date_nanos 型別。
支援的格式:
- 標準格式:
yyyy-MM-ddTHH:mm:ss.SSSZ(例如:2023-01-15T08:30:00.000Z) - 簡化格式:
yyyy-MM-dd(例如:2023-01-15) - 預設時區為 UTC。
格式行為差異:
不同精度的日期格式在查詢時會有不同的行為,以下是關鍵差異:
// 查詢到「年」時,會精確比對該年的第一秒
{
"query": {
"query_string": {
"query": "timestamp:2023" // 等同於 ="2023-01-01T00:00:00Z"
}
}
}
// 查詢到「月」時,會精確比對該月的第一秒
{
"query": {
"query_string": {
"query": "timestamp:2023-02" // 等同於 ="2023-02-01T00:00:00Z"
}
}
}
// 當精度達到「日」,行為開始改變
// 這會查詢該日期的整個區間範圍
{
"query": {
"query_string": {
"query": "timestamp:2023-03-01" // 查詢 >="2023-03-01T00:00:00Z" <"2023-03-02T00:00:00Z"
}
}
}
// 精度到「小時」時,查詢該小時的整個區間
{
"query": {
"query_string": {
"query": "timestamp:2023-03-01T08" // 查詢 >="2023-03-01T08:00:00Z" <"2023-03-01T09:00:00Z"
}
}
}
// 精度到「分鐘」時,需要用雙引號(因包含冒號)
{
"query": {
"query_string": {
"query": "timestamp:\"2023-03-01T08:00\"" // 查詢 >="2023-03-01T08:00:00Z" <"2023-03-01T08:01:00Z"
}
}
}使用注意事項
1. 標準格式需要使用雙引號
因為標準格式包含冒號 :,在 QueryString 中會被視為特殊字元,必須用雙引號包起來:
❌ 錯誤寫法(會產生解析錯誤):
{
"query": {
"query_string": {
"query": "timestamp:2023-01-15T08:30:00Z"
}
}
}✅ 正確寫法:
// 方法 1:使用雙引號包起來
{
"query": {
"query_string": {
"query": "timestamp:\"2023-01-15T08:30:00Z\""
}
}
}
// 方法 2:使用簡化格式(不含冒號)
{
"query": {
"query_string": {
"query": "timestamp:2023-01-15"
}
}
}2. 日期查詢不支援比較運算子
當使用比較運算子查詢日期時,查詢會失效或產生錯誤:
// 這個查詢實際上會在「全部欄位」中搜尋符合該日期的資料
// 而不是在 timestamp 欄位中進行比較
{
"query": {
"query_string": {
"query": "timestamp:>=\"2023-01-15T08:30:00Z\""
}
}
}
// 若改用 default_field 或 fields,會直接產生解析錯誤
{
"query": {
"query_string": {
"query": ">=\"2023-01-15T08:30:00Z\"",
"fields": ["timestamp"] // ❌ 會報錯
}
}
}
{
"query": {
"query_string": {
"query": ">=\"2023-01-15T08:30:00Z\"",
"default_field": "timestamp" // ❌ 會報錯
}
}
}✅ 正確做法:使用範圍查詢語法
{
"query": {
"query_string": {
"query": "timestamp:[2023-01-15T08:30:00Z TO *]"
}
}
}3. 自訂格式的影響
當 date 型別的欄位有指定 format 時(非預設的 strict_date_optional_time||epoch_millis),查詢格式必須完全符合指定格式:
// 假設欄位定義如下
"timestamp": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss'Z'"
}使用錯誤格式會導致不同結果:
// 在 query 中直接指定欄位:查詢無結果(靜默失敗)
{
"query": {
"query_string": {
"query": "timestamp:[2023-01-15T08:30 TO *]" // 格式不符
}
}
}
// 使用 default_field 或 fields:產生錯誤訊息
{
"query": {
"query_string": {
"query": "[2023-01-15T08:30 TO *]",
"default_field": "timestamp" // 會報錯:failed to parse date field
}
}
}錯誤訊息範例:
failed to parse date field [2023-01-15T08:30] with format [yyyy-MM-dd'T'HH:mm:ss'Z']其他參數
1. 欄位相關參數
default_field vs fields:
default_field: 指定預設搜尋的單一欄位。fields: 指定多個搜尋欄位及其權重。
// 使用 default_field
{
"query_string": {
"query": "apple",
"default_field": "content"
}
}
// 使用 fields
{
"query_string": {
"query": "apple",
"fields": ["title^2", "content", "tags"]
}
}2. analyzer
指定 query_string 如何處理和分析查詢字串,Elasticsearch 提供多種內建分析器,詳細列表可參考官方文件。
{
"query_string": {
"query": "The Quick Brown Fox",
"analyzer": "standard"
}
}重要概念:索引時 vs 查詢時分析器
Elasticsearch 有兩個階段會使用分析器:
1. 索引時分析器(Index-time Analyzer)
- 處理存入索引的資料。
- 例子:text 欄位存入
"Wing Chou"→ 分詞為["wing", "chou"]。
2. 查詢時分析器(Query-time Analyzer)
- 處理查詢字串。
query_string的analyzer參數控制此階段。
實例說明
假設 text 欄位已存入 "Wing Chou",索引時分詞為 ["wing", "chou"]:
// ✅ 使用 standard 分析器
// 查詢字串被分析為 ["wing", "chou"],然後預設運算子為 OR,因為不論是 wing 還是 chou 都可以比對到資料
{
"query_string": {
"query": "Wing Chou",
"analyzer": "standard"
}
}
// ❌ 使用 keyword 分析器,錯誤查詢條件
// 查詢字串保持完整 "Wing Chou",無法符合分詞結果
{
"query_string": {
"query": "Wing Chou",
"analyzer": "keyword"
}
}
// 查詢字串保持 "Wing"(大寫),無法符合資料中的 "wing"(小寫)
{
"query_string": {
"query": "Wing",
"analyzer": "keyword"
}
}
// ✅ 使用 keyword 分析器,正確查詢條件
{
"query_string": {
"query": "wing",
"analyzer": "keyword"
}
}
{
"query_string": {
"query": "wing OR chou",
"analyzer": "keyword"
}
}3. analyze_wildcard
控制是否對萬用字元表達式進行分析處理。官方文件說明如下:
(選用參數,布林值)若設為
true,查詢時會嘗試對萬用字元詞彙進行分析處理。預設為false。需要注意的是,即使設為
true,也只有結尾是*的查詢才會進行完整分析。開頭或中間包含*的查詢只會進行正規化處理。
{
"query_string": {
"query": "Te*",
"analyze_wildcard": true,
"analyzer": "standard"
}
}參數值說明
analyze_wildcard: false(預設):萬用字元表達式不經過分析器處理analyze_wildcard: true:萬用字元表達式會經過分析器處理,但處理方式取決於萬用字元位置:- 結尾萬用字元(如
Te*):進行完整分析 - 開頭或中間萬用字元(如
*Te*、T*e):只進行正規化
- 結尾萬用字元(如
實測觀察與疑問
在實際測試中發現,這個參數的行為與官方說明存在一些不一致或難以理解的地方:
1. Text 欄位的行為
不管 analyze_wildcard 設定為 true 或 false,查詢都是大小寫不敏感:
// 以下兩個查詢結果相同,都能匹配到資料
{
"query_string": {
"query": "name:Te*",
"analyze_wildcard": true
}
}
{
"query_string": {
"query": "name:Te*",
"analyze_wildcard": false
}
}2. Keyword 欄位不指定 analyzer
不管 analyze_wildcard 設定為 true 或 false,查詢都是大小寫敏感:
// 以下兩個查詢結果相同,都只能精確匹配大小寫
{
"query_string": {
"query": "email:Te*",
"analyze_wildcard": true
}
}
{
"query_string": {
"query": "email:Te*",
"analyze_wildcard": false
}
}3. Keyword 欄位指定 analyzer 時的矛盾行為
當對 keyword 欄位指定 analyzer: "standard" 時,出現了與官方說明不一致的現象(也可能是我對「完整分析」與「正規化」的理解有誤):
// 開頭或中間有萬用字元:會轉小寫(符合「正規化」說明)
// 實際查詢:*te*
{
"query_string": {
"query": "email:(*Te*)",
"analyze_wildcard": true,
"analyzer": "standard"
}
}
// 結尾萬用字元:不會轉小寫(與「完整分析」說明矛盾)
// 實際查詢:Te*
{
"query_string": {
"query": "email:(Te*)",
"analyze_wildcard": true,
"analyzer": "standard"
}
}根據官方說明,結尾萬用字元應該進行「完整分析」,理論上 Te* 應該被 standard analyzer 轉換成 te*,但實測結果卻是保持 Te* 不變。
萬用字元位置的處理差異
| 萬用字元模式 | 官方說明的處理方式 | Keyword + standard analyzer 實測 |
|---|---|---|
Te* | 完整分析 | 不轉小寫(Te*) |
*Te* | 只正規化 | 會轉小寫(*te*) |
*Te | 只正規化 | 會轉小寫(*te) |
T*e | 只正規化 | 會轉小寫(t*e) |
4. auto_generate_synonyms_phrase_query
控制同義詞處理方式:
true(預設):自動為同義詞生成片語查詢,保持詞序和相鄰性。false:只生成普通同義詞查詢,不考慮詞序。
例如,若設定 "ny" 與 "new york" 為同義詞:
{
"query_string": {
"query": "ny restaurants",
"auto_generate_synonyms_phrase_query": true
}
}- true:會比對 "ny restaurants" 或 "new york restaurants"("new york" 作為整體片語)。
- false:會比對 "ny restaurants" 或 "new restaurants" 或 "york restaurants"。
5. 權重控制:boost 與欄位加權
Elasticsearch 提供兩種層級的權重控制機制:
5.1 欄位加權(Field Boost)
使用 ^ 語法調整特定欄位的權重。
{
"query_string": {
"query": "apple iphone",
"fields": ["title^3", "description^2", "content"]
}
}- 功能:控制同一個查詢中不同欄位的相對重要性。
- 作用方式:
- 每個欄位各自獨立計算基礎分數(基於 BM25 演算法)。
- title 欄位的分數會乘以 3。
- description 欄位的分數會乘以 2。
- content 欄位的分數乘以 1(預設值)。
- 最後將所有加權後的欄位分數相加,得到最終分數。
- 重要說明:
title^3並非表示 title 的最終得分是 content 的 3 倍,而是表示 title 欄位的基礎分數會被放大 3 倍後,再與其他欄位組合。最終分數還會受到詞頻、逆文件頻率、文件長度等因素影響。 - 適用場景:多欄位搜尋時,某些欄位(如標題)比其他欄位(如內容)更能代表文件主題。
計算範例(基礎分數為假設值):
假設搜尋 "apple",各欄位的基礎分數如下:
| 欄位 | 基礎分數 | 加權後分數 |
|---|---|---|
| title | 2.0 | 2.0 × 3 = 6.0 |
| description | 1.5 | 1.5 × 2 = 3.0 |
| content | 2.5 | 2.5 × 1 = 2.5 |
| 最終分數 | 11.5 |
注意:上述基礎分數為假設性範例,用於說明計算邏輯。實際分數會依照索引狀態、文件內容、詞頻等因素而有所不同,需使用
_explainAPI 查看真實評分過程。
5.2 查詢層級 boost(Query Boost)
調整整個查詢子句的權重。
{
"query_string": {
"query": "apple iphone",
"boost": 2.0
}
}- 功能:在複合查詢(如 bool query)中調整整個查詢子句的重要性。
- 重要限制:如果單獨使用一個查詢,boost 參數對排序沒有影響(所有文件的分數都乘以相同倍數,相對排序不會改變)。
- 主要用途:
- 在
boolquery 的should子句中,調整不同查詢條件的相對重要性。 - 讓某些匹配條件比其他條件對最終排序有更大影響。
- 體現業務邏輯中不同搜尋維度的重要性差異。
- 在
- 適用場景:結合多種查詢方式(文字搜尋、精確匹配、範圍查詢等),需要調整它們對最終排序的影響權重。
5.3 兩者結合使用
範例
{
"query": {
"bool": {
"should": [
{
"query_string": {
"query": "apple",
"fields": ["title^2"],
"boost": 2.0
}
},
{
"query_string": {
"query": "iphone",
"fields": ["description"],
"boost": 4.0
}
}
]
}
}
}計算說明(基礎分數為假設值):
假設有以下三個文件:
| 文件 | title 包含 "apple" | description 包含 "iphone" | 分數計算 |
|---|---|---|---|
| 文件 A | ✅ (基礎分 3.0) | ✅ (基礎分 2.0) | (3.0 × 2 × 2.0) + (2.0 × 1 × 4.0) = 20.0 |
| 文件 B | ✅ (基礎分 2.5) | ❌ | (2.5 × 2 × 2.0) + 0 = 10.0 |
| 文件 C | ❌ | ✅ (基礎分 2.5) | 0 + (2.5 × 1 × 4.0) = 10.0 |
排序結果:文件 A (20.0) > 文件 B (10.0) = 文件 C (10.0)
分析:
- 文件 A 同時匹配兩個條件,獲得最高分。
- 文件 B 只匹配 title 中的 "apple":欄位基。礎分 2.5 × 欄位 boost 2 × 查詢 boost 2.0 = 10.0。
- 文件 C 只匹配 description 中的 "iphone":欄位基礎分 2.5 × 欄位 boost 1 × 查詢 boost 4.0 = 10.0。
即使文件 C 的查詢 boost (4.0) 比文件 B 的 (2.0) 高,但因為文件 B 有欄位 boost (^2),實際結果仍需依照基礎分數而定。
注意:上述基礎分數為假設性範例,實際分數需使用
_explainAPI 查看。
5.4 關鍵差異
| 特性 | 欄位加權 (^) | 查詢 boost (boost) |
|---|---|---|
| 作用範圍 | 單一查詢內的不同欄位 | 複合查詢中的不同查詢子句 |
| 控制對象 | 欄位間的相對權重 | 查詢子句間的相對權重 |
| 使用位置 | fields 參數中 | 查詢子句的頂層參數 |
| 單獨使用 | 有效(影響欄位分數組合) | 無效(不改變排序) |
| 典型場景 | 標題比內容重要 | 使用者搜尋比篩選條件重要 |
6. 模糊搜尋(fuzziness 與 phrase_slop)
波浪號 ~ 在 QueryString 中有兩種不同用途,取決於它的位置:
6.1 模糊搜尋(單詞後的波浪號)
apple~ // 單詞後接波浪號,表示模糊搜尋
apple~2 // 指定模糊度為 2- 對應參數:
fuzziness。 - 功能:處理單個詞的拼寫錯誤,基於編輯距離。
- 識別方式:用於單詞後面。
模糊度值的限制:
- 有效值:
0、1、2或"AUTO"。 - 超過 2 會報錯:
Valid edit distances are [0, 1, 2]。
fuzziness 參數生效條件:
fuzziness 參數只在查詢字串中有單詞使用 ~(但未指定數字)時才會生效:
// ✅ 單詞有 ~,無數字,未設定 fuzziness:預設模糊度為 1
{
"query_string": {
"query": "apple~" // apple 使用模糊度 1(預設值)
}
}
// ✅ 單詞有 ~,無數字:使用 fuzziness 參數
{
"query_string": {
"query": "apple~",
"fuzziness": 2 // 生效,apple 使用模糊度 2
}
}
// ❌ 單詞無 ~:不生效
{
"query_string": {
"query": "apple banana",
"fuzziness": 1 // 不生效,兩個詞都是精確匹配
}
}
// ❌ 單詞有 ~N(明確數字):以查詢字串中的數字為準
{
"query_string": {
"query": "apple~2",
"fuzziness": 1 // 不生效,以查詢字串中的 2 為準
}
}
// ⚠️ 混用情況:只有帶 ~ 的詞會套用模糊搜尋
{
"query_string": {
"query": "apple~2 banana",
"fuzziness": 1 // 不生效,apple 用 2,banana 精確匹配
}
}
{
"query_string": {
"query": "apple~ banana",
"fuzziness": 1 // 只對 apple 生效(模糊度 1),banana 精確匹配
}
}優先順序規則:
- 查詢字串中的
~N(明確數字):直接使用該數字 - 查詢字串中的
~(無數字)+fuzziness參數:使用fuzziness參數值 - 查詢字串中的
~(無數字)+ 未設定fuzziness:預設模糊度為 1 - 查詢字串中沒有
~:該詞為精確匹配,fuzziness參數不生效
⚠️ 重要注意事項:
fuzziness 參數必須搭配查詢字串中的 ~ 才會生效。如果詞彙後面沒有 ~,該詞會被視為精確匹配,無論 fuzziness 參數設定為何。
fuzziness 設定差異:
"fuzziness": "AUTO":根據詞長自動調整。預設行為等同於AUTO:3,6,規則如下:- 詞長 0-2 字元:fuzziness = 0(必須精確匹配)
- 詞長 3-5 字元:fuzziness = 1
- 詞長 6+ 字元:fuzziness = 2
"fuzziness": "AUTO:[low],[high]":自訂閾值的 AUTO 模式。例如AUTO:4,7代表:- 詞長 0-3 字元:fuzziness = 0
- 詞長 4-6 字元:fuzziness = 1
- 詞長 7+ 字元:fuzziness = 2
"fuzziness": 1或"fuzziness": 2:固定允許的最大編輯距離
詳細說明請參考官方文件。
範例說明:
apple~1可比對出 "aple"、"appla" 等拼寫錯誤的詞。
6.2 近似搜尋(片語後的波浪號)
"apple banana"~5 // 片語後接波浪號,表示近似搜尋- 對應參數:
phrase_slop - 功能:處理片語中詞的順序和距離
- 識別方式:用於引號包圍的片語後面
Slop 值的計算邏輯:
Slop 代表詞彙需要「移動」的最小步數,可以處理:
- 詞彙間有其他詞穿插。
- 詞彙順序不對(對調)。
計算方式說明:
假設索引中有 "quick brown fox jumps"
// 範例 1:詞彙間有穿插
查詢:"quick fox"
索引:"quick brown fox"
→ "fox" 需要往左移動 1 步跳過 "brown"
→ slop = 1
// 範例 2:相鄰詞序對調
查詢:"brown quick"
索引:"quick brown"
→ 兩個詞互換位置
→ slop = 2(官方文件說明:對調成本為 2)
// 範例 3:不相鄰詞序對調 + 穿插
查詢:"fox quick"
索引:"quick brown fox"
→ "fox" 需要移動到 "quick" 前面,跨過 2 個位置
→ slop = 3實際範例:
// slop = 0:必須完全符合
{
"query_string": {
"query": "\"quick brown\""
}
}
// ✅ 匹配:"quick brown fox"
// slop = 1:允許中間有 1 個詞
{
"query_string": {
"query": "\"quick fox\"~1"
}
}
// slop = 2:允許相鄰詞對調
// ✅ 匹配:"quick brown fox"
// ❌ 不匹配:"quick fox"
{
"query_string": {
"query": "\"brown quick\"~2"
}
}
// slop = 3:允許更複雜的移動
// ✅ 匹配:"quick brown fox"
{
"query_string": {
"query": "\"fox quick\"~3"
}
}在 API 中設定:
{
"query_string": {
"query": "apple~2 \"quick fox\"~3",
"fuzziness": "AUTO", // 全域設定,會被查詢中的具體值覆蓋
"phrase_slop": 2 // 全域設定,會被查詢中的具體值覆蓋
}
}優先順序:
查詢字串中使用 ~ 設定的值會覆蓋 API 參數中的全域設定。
分頁與排序
分頁參數
{
"query": {
"query_string": {
"query": "apple"
}
},
"from": 0, // 起始位置,預設為 0
"size": 10 // 每頁數量,預設為 10
}from:指定從第幾筆結果開始回傳(0 代表第一筆)size:指定要回傳幾筆結果
注意事項:
- 深度分頁(
from+size過大)會影響效能。 - Elasticsearch 預設限制
from+size不能超過 10000。 - 如需處理大量資料,建議使用 Search After 或 Scroll API。
排序參數
sort 參數接受陣列,可以指定多個排序條件,排序優先順序由陣列順序決定。
排序語法
方式 1:簡單欄位名稱(預設升序)
{
"sort": ["price"] // 按 price 升序排序
}方式 2:欄位 + 排序方向物件
{
"sort": [
{ "price": "asc" } // 按 price 升序
]
}方式 3:完整設定物件
{
"sort": [
{
"price": {
"order": "desc", // 排序方向:asc(升序)或 desc(降序)
"missing": "_last" // 缺少該欄位的文件排在最後
}
}
]
}多欄位排序
{
"query": {
"query_string": {
"query": "apple"
}
},
"sort": [
{ "price": "asc" }, // 第一優先:按價格升序
{ "created_at": "desc" }, // 第二優先:價格相同時按建立時間降序
"_score" // 第三優先:其他條件相同時按相關性分數排序
]
}特殊排序值
"_score":按查詢相關性分數排序(預設為降序)。"_doc":按文件的內部順序排序(最快,但順序不固定)。
排序方向
"asc":升序(Ascending)- 從小到大。"desc":降序(Descending)- 從大到小。
處理缺失值
使用 missing 參數指定缺少排序欄位的文件應該排在哪裡:
{
"sort": [
{
"price": {
"order": "asc",
"missing": "_last" // 選項:_first(排最前)、_last(排最後)、或指定預設值
}
}
]
}完整範例
{
"query": {
"query_string": {
"query": "laptop"
}
},
"from": 0,
"size": 20,
"sort": [
{ "price": { "order": "asc", "missing": "_last" } },
{ "rating": "desc" },
"_score"
]
}排序邏輯說明:
- 優先按價格升序排列(沒有價格的排最後)。
- 價格相同時,按評分降序排列。
- 價格和評分都相同時,按相關性分數排列。
特殊字元轉義
QueryString 中有許多特殊字元具有特定含義,若要作為普通字元使用,需要使用反斜線 \ 轉義:
\+ \- \= \&\& \|\| \> \< \! \( \) \{ \} \[ \] \^ \" \~ \* \? \: \\ \/例如:
- 搜尋包含加號的文件:
title:\+1。 - 搜尋包含括號的文件:
content:\(sample\)。 - 搜尋包含引號的文件:
description:\"quoted text\"。
異動歷程
- 2025-04-13 初版文件建立。
- 2025-10-03
- 修正語句用詞,統一使用台灣慣用語。
- 修正日期查詢範圍語法說明(日期欄位不支援比較運算子,應使用範圍查詢語法)。
- 修正權重計算遺漏欄位基礎分數的部分。
- 補充技術細節。
